#ifndef SPLINEBASE_HPP_
#define SPLINEBASE_HPP_

//#include "/usr/include/eigen3/Eigen/Dense"
#include <algorithm>
#include <cstddef>
//#include <eigen3/Eigen/src/Core/Matrix.h>
#include <vector>
#include "matplotlibcpp.h"
#include <string>

namespace plt = matplotlibcpp;

class SplineBase {
public:
  typedef std::vector<double> vector_type ;
  enum bd_type{
    complete = 1,
    natural = 2,
    periodic = 3
  };
protected:
  vector_type  xData, yData;

// protected:
//   Eigen::VectorXd xView, yView;

public:
  SplineBase(): xData(0), yData(0) {}
  SplineBase(const SplineBase &) = default;
  SplineBase(SplineBase &&) = default;
  SplineBase(vector_type x, vector_type y): xData(x),yData(y){}
  SplineBase &operator=(const SplineBase &) = default;
  SplineBase &operator=(SplineBase &&) = default;
  ~SplineBase(){}

  size_t get_closest_left_idx(double x) const;
  void draw(std::string file_name) const;
  virtual double interpolate(double x) const{
    return 0;
  }
};

inline size_t SplineBase::get_closest_left_idx(double x) const {
    //std::vector<double>::const_iterator it;
    auto it = std::upper_bound(xData.begin(), xData.end()-1, x);
    // *it > x
    size_t idx = std::max(static_cast<int>(it - xData.begin()) - 1, 0);
    // m_x[idx] <= x
    return idx;
}

inline void SplineBase::draw(std::string file_name) const{
  std::vector<double> x,y;
  double stepsize = 0.01;
  double current = xData[0];
  while(current <= *(xData.end()-1)){
    x.push_back(current);
    y.push_back(interpolate(current));
    current += stepsize;
  }
  plt::figure_size(1200, 780);
  plt::plot(x, y); 
  plt::plot(xData, yData, "o");
  plt::save(file_name,300);
  plt::show();
}

#endif // SplineBase.hpp